#!/usr/bin/env python
# -*- coding: utf-8 -*-

import gtk

import struct
import array

import pluginmanager

@pluginmanager.register('PLUGIN-REGISTER')
def mega_register(*args, **kwargs):
    return {'M&B PWNED':'FORTE'}

@pluginmanager.register('FORTE-SCAN')
def mega_scan(*args, **kwargs):
    fd = kwargs['file']
    progbar = kwargs['progbar']

    fd.seek(0xA0, 0)
    if not fd.read(12) == 'MEGAMAN&BASS':
        return []

    number = 356
    base_address = 0x64BA38
    results = []

    fd.seek(0x5079D8, 0)
    for x in range(number):
        percent = float(x+1)/float(number)
        progbar.set_text('PWNING M&B: ' + str(int(percent * 100)) + "%")
        progbar.set_fraction(percent)

        while gtk.events_pending():
            gtk.main_iteration()

        results.append((base_address + struct.unpack('<L', fd.read(4))[0], 'FORTE'))
        fd.read(4) #Pula segunda flag do header

    return results

@pluginmanager.register('FORTE-DECODER')
def mega_decoder(*args, **kwargs):
    address = kwargs['address']
    fd = kwargs['file']

    number = 356
    base_address = 0x64BA38
    rel = address - base_address
    output = array.array('c')

    fd.seek(0x5079D8, 0)
    for x in range(number):
        if struct.unpack('<L', fd.read(4))[0] == rel:
            break
        fd.read(4)

    data_size = struct.unpack('<L', fd.read(4))[0]

    fd.seek(address, 0)
    while len(output) < data_size:
        flag = struct.unpack('B', fd.read(1))[0]
        for x in range(8):
            if ((flag << x) & 0x80) == 0:
                output.append(fd.read(1))
            else:
                par1 = struct.unpack('B', fd.read(1))[0]
                par2 = struct.unpack('B', fd.read(1))[0]
                size = par1 >> 2
                distance = ((par1 & 3) << 8) | par2
                for x in range(size):
                    output.append(output[len(output)  - distance])
            if len(output) >= data_size:
                break

    return output
